package com.iliad2x.pdf.images
{
	import com.iliad2x.utils.Gc;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.geom.Matrix;
	import flash.net.FileReference;
	import flash.utils.ByteArray;
	
	import mx.controls.Alert;
	
	import spark.components.Image;

	public class ImageControl extends Image
	{
		public static const LOAD_COMPLETE:String = "loadComplete";
		private var _file:FileReference;
		
		/** Setter FileReference **/
		public function set file($value:FileReference):void
		{
			_file = $value;
			loadFileReference();
		}
		
		public function ImageControl()
		{
			addEvents();
			super();
		}
		
		/** FileReference Load **/
		private function loadFileReference():void
		{
			if(!_file)
				return;
			
			addFileEvents();
			_file.load();
		}
		
		/** FileReference Load Complete **/
		protected function fileLoadCompleteHandler(e:Event):void
		{
			removeFileEvents();
			loadBytes((e.target as FileReference).data);
		}
		
		/** FileReference IOError **/
		protected function fileIOErrorHandler(e:IOErrorEvent):void
		{
			removeFileEvents();
			trace(e.text);
			Alert.show("Image IOError!","Error");
		}
		
		/** Add FileReference Events **/
		private function addFileEvents():void
		{
			_file.addEventListener(Event.COMPLETE, fileLoadCompleteHandler);
			_file.addEventListener(IOErrorEvent.IO_ERROR, fileIOErrorHandler);
			_file.addEventListener(IOErrorEvent.DISK_ERROR, fileIOErrorHandler);
		}
		
		/** Remove FileReference Events **/
		private function removeFileEvents():void
		{
			_file.removeEventListener(Event.COMPLETE, fileLoadCompleteHandler);
			_file.removeEventListener(IOErrorEvent.IO_ERROR, fileIOErrorHandler);
			_file.removeEventListener(IOErrorEvent.DISK_ERROR, fileIOErrorHandler);
		}
		
		/** File Bytes Load Function **/
		private function loadBytes($value:ByteArray):void
		{	
			var loader:Loader = new Loader;
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadBytesCompleteHandler);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadBytesIOErrorHandler);
			loader.loadBytes($value);
			loader = null;
			_file.data.clear();
		}
		
		/** File Bytes Load Complete **/
		private function loadBytesCompleteHandler(e:Event):void
		{
			var loaderinfo:LoaderInfo = e.target as LoaderInfo;
			var bitmap:Bitmap = loaderinfo.content as Bitmap;
			var bitdata:BitmapData = bitmap.bitmapData;
			var scale:Number = 1;
			if(width)
			{
				scale = width / bitmap.width;
				if(height)
				{
					if((height*scale) > height)
						scale = height / bitmap.height;
				}
			}
			
			if(height)
			{
				scale = height / bitmap.height;
				if(width)
				{
					if((width*scale) > width)
						scale = width / bitmap.width;
				}
			}
			
			var mat:Matrix = new Matrix;
			mat.scale(scale, scale);
			
			var bd:BitmapData = new BitmapData(bitmap.width * scale, bitmap.height * scale,true);
			bd.draw(bitdata, mat, null, null, null, true);
			
			source = bd;
			
			super.width = bitmap.width * scale;
			super.height = bitmap.height * scale;
						
			bitmap = null;
			bitdata = null;
			
			dispatchEvent(new Event(LOAD_COMPLETE));
		}
		
		/** File Bytes IOError **/
		private function loadBytesIOErrorHandler(e:IOErrorEvent):void
		{
			trace(e.text);
			Alert.show("Image IOError!","Error");
		}
		
		/** Image Load Completed **/
		protected function loadCompleteHandler(e:Event):void
		{
			removeEvents();
			var loader:LoaderInfo = e.target as LoaderInfo;
			trace("loader.content = ",loader.content.width, loader.content.height);
			callLater(gc);
		}
		
		/** Image Load InputOutput Error **/
		protected function errorHandler(e:IOErrorEvent):void
		{
			removeEvents();
			trace(e.text);
			Alert.show("Image IOError!","Error");
		}
		
		/** Add Events **/
		private function addEvents():void
		{
			trace("addEvents()");
			addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			addEventListener(Event.COMPLETE, loadCompleteHandler);
		}
		
		/** Remove Events **/
		private function removeEvents():void
		{
			removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			removeEventListener(Event.COMPLETE, loadCompleteHandler);
		}
		
		private function gc():void
		{
			Gc.dogc();
		}
	}
}